package com.wu.server.spider;


import com.wu.server.Thread.MainThread;
import com.wu.server.code.Code;
import com.wu.server.config.EncodeJson;
import com.wu.server.dao.GoodsRepository;
import com.wu.server.dao.GoodsTagRepository;
import com.wu.server.dao.GoodsTypeRepository;
import com.wu.server.dao.ShopRepository;
import com.wu.server.entity.Goods;
import com.wu.server.entity.Type;
import com.wu.server.websocket.MetaWebSocket;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.EncodeException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author Wugs
 * @version 1.0
 * @date 2021/2/26 19:44
 */
@Component
public class JdSpider {
    @Autowired
    GoodsRepository goodsRepository;
    @Autowired
    GoodsTypeRepository goodsTypeRepository;
    @Autowired
    GoodsTagRepository goodsTagRepository;
    @Autowired
    ShopRepository shopRepository;
    @Autowired
    MainThread mainThread;
    @Autowired
    Code code;
    @Autowired
    EncodeJson encodeJson;


    Integer page_num = 0;//页码
    Integer goods_num = 0;//商品数目
    String kb;//输入内容
    String js_bottom = "var q=document.documentElement.scrollTop=10000";//滚动
    Integer sleep = 3000;//延迟
    String title;//商品名称
    Double prince;//价格
    Integer sales;//总评论
    String goods_src;//商品链接
    String goods_img;//商品图片
    String shop_name = null;//店铺名称
    String shop_src = null;//店铺地址
    String tagName = "";//标签
    String check = "";
    public void start(String kb) {
        this.kb = kb;
        String url = "https://search.jd.com/Search?keyword=" + this.kb + "&page=1";
        if (kb == null || kb.equals("")) {
            sendText(code.EXECUTE);
            mainThread.run();
            return;
        }
        goodsRepository.deleteAll();
        goodsTypeRepository.deleteAll();
        System.setProperty("webdriver.edge.driver", "./edge.exe");
        EdgeDriver edge = new EdgeDriver();
        try {
            System.out.print("\033[H\033[2J");
            System.out.flush();
            System.out.println("--------------------开始爬取商品--------------------");
            openUrl(edge, url);//访问
            getGoodsType(edge);
            getGoodsInfo(edge);
        } catch (Exception e) {
            e.printStackTrace();
            sendText(code.EXECUTE);
            mainThread.run();
        }


    }

    /**
     * 获取商品标签项
     * TODO: 2021/3/1  捕获商品标签，并存入数据库
     *
     * @param edge
     * @throws Exception
     */
    private void getGoodsType(EdgeDriver edge) throws Exception {
        System.out.println("开始爬取分类信息");
        sendText(code.SPIDER_TYPE);
        List<WebElement> ul_list = new ArrayList<>(); //定义UL数组
        List<WebElement> li_list = new ArrayList<>(); //定义li数组
        WebElement div = edge.findElementById("J_selectorSenior");
        WebElement wrap = div.findElement(By.className("sl-wrap")).findElement(By.className("sl-tab-cont"));
        List<WebElement> div_list = wrap.findElements(By.xpath("./div"));
        Integer id = 0;
        int max = 5;
        if(div_list.size()<5){
            max = li_list.size();
        }
        for (int i = 0 ; i < max; i++) {
            ul_list.add(div_list.get(i).findElement(By.xpath("./div[1]/ul")));
        }
        for (WebElement ul : ul_list) {
            li_list = ul.findElements(By.xpath("./li"));
            for (WebElement li : li_list) {
                String url = li.findElement(By.xpath("./a")).getAttribute("onclick");
                String[] text = url.split("\'");
                if (text[1].equals("其它")||text[1].equals("其他")) {
                    break;
                } else {
                    ++id;
                    Type item = new Type();
                    item.setId(id);
                    item.setType_name(text[1]);
                    item.setType_sales(0);
                    item.setType_sum(0);
                    goodsTypeRepository.save(item);
                }
            }
        }
        System.out.println("分类信息爬取完成,累计" + id + "条标签");
        sendText(code.TYPE_FINISH);
    }

    /**
     * 获得主页搜索商品
     * TODO 解析商品店铺地址，在调用方法进行店铺访问
     *
     * @param edge
     * @throws InterruptedException
     */
    private void getGoodsInfo(EdgeDriver edge) throws Exception {
        this.page_num++;//页++
        edge.executeScript(this.js_bottom);//向下滚动
        Thread.sleep(this.sleep);
        List<WebElement> list = edge.findElementsByXPath("//*[@id=\"J_goodsList\"]/ul/li");//商品列表所有标签
        String next_page_sign = edge.findElementByClassName("pn-next").getAttribute("onclick");//翻页组件
        System.out.println("第" + this.page_num + "页.......");
        sendText(code.SPIDER_GOODS);
        for (WebElement li : list) {
            // TODO: 2021/3/1 判断是否有滚动
            if (li.findElement(By.xpath("./div/div[2]")).getAttribute("class").equals("p-price")) {
                saveSelf(li);//存放自营
            } else {
                aboutShop(li);//存放普通
            }
        }
        System.out.println("第" + this.page_num + "页数据存储完成");
        System.out.println("爬取" + this.goods_num + "条商品");
        if (next_page_sign == null) {
            System.out.println("--------------------所有商品存储完成--------------------");
            System.out.println("累计" + this.goods_num + "条商品数据");
            sendText(code.GOODS_FINISH);
            this.page_num = 0;
            edge.quit();
            sendText(code.EXECUTE);
            mainThread.run();
        } else {
            edge.findElementByClassName("pn-next").click();
            getGoodsInfo(edge);
        }

    }

    /**
     * 存储自营数据
     * @param li
     */
    private void saveSelf(WebElement li) {
        Goods item = new Goods();//商品名
        goods_src = li.findElement(By.xpath("./div/div[1]/a|./div/div/div[2]/div[1]/a")).getAttribute("href");//商品地址
        goods_img = li.findElement(By.xpath("./div/div[1]/a/img|./div/div/div[2]/div[1]/a/img")).getAttribute("src");//商品图片地址
        if (goods_img == null) {
            goods_img = li.findElement(By.xpath("./div/div[1]/a/img")).getAttribute("data-lazy-img");
        }
        prince = getNumber(li.findElement(By.xpath("./div/div[2]/strong")).getText());//商品价格
        title = li.findElement(By.xpath("./div/div[3]/a")).getText();//商品名称
        sales = getCommitNum(li.findElement(By.xpath("./div/div[4]/strong/a")).getText());//总评论数
        shop_name = li.findElement(By.xpath("./div/div[5]/span/a|./div/div[5]")).getText();//店铺名称
        shop_src = li.findElement(By.xpath("./div/div[5]/span/a|./div/div[5]")).getAttribute("href");//店铺地址
        if (shop_name.equals("")) {
            shop_name = "京东自营";
            shop_src = "京东自营";
        }else{
            shop_src = li.findElement(By.xpath("./div/div[5]/span/a")).getAttribute("href");//店铺地址
        }
        List<WebElement> tag_list;
        tag_list = li.findElements(By.xpath("./div/div[6]/i"));//标签
        for (WebElement i : tag_list) {
            tagName += i.getText() + ",";

        }
        ++this.goods_num;
        item.setId(this.goods_num);
        item.setTitle(title);
        item.setPrince(prince);//价格
        if(prince>20000){
            return;
        }
        item.setShop_name(shop_name);//店铺名
        item.setShop_src(shop_src);//店铺地址
        item.setSales(sales);//销量
        item.setGoods_img(goods_img);//商品图片
        item.setGoods_src(goods_src);//详情地址
        item.setTag_name(tagName);
        goodsRepository.save(item);
        tagName = "";
    }

    /**
     * 存储第三方商品数据
     * @param li
     */
    private void aboutShop(WebElement li) {
        Goods item = new Goods();//商品名
        goods_src = li.findElement(By.xpath("./div/div[1]/a|./div/div/div[2]/div[1]/a")).getAttribute("href");//商品地址
        goods_img = li.findElement(By.xpath("./div/div[1]/a/img|./div/div/div[2]/div[1]/a/img")).getAttribute("src");//商品图片地址
        if (goods_img == null) {
            goods_img = li.findElement(By.xpath("./div/div[1]/a/img")).getAttribute("data-lazy-img");
        }
        prince = getNumber(li.findElement(By.xpath("./div/div[3]/strong")).getText());//商品价格
        title = li.findElement(By.xpath("./div/div[4]/a")).getText();//商品名称
        check = li.findElement(By.xpath("./div/div[7]")).getAttribute("data-selfware");//检查是否缺失店铺标签
        sales = getCommitNum(li.findElement(By.xpath("./div/div[5]/strong/a")).getText());//总评论数
        List<WebElement> tag_list;
        tag_list = li.findElements(By.xpath("./div/div[8]/i"));//标签
        for (WebElement i : tag_list) {
            tagName += i.getText() + ",";
        }
        if (check.equals("1")) {//店铺标签为空
            shop_name = "京东自营";
            shop_src = "京东自营";
        } else {
            shop_name = li.findElement(By.xpath("./div/div[7]/span/a")).getText();//店铺名称
            shop_src = li.findElement(By.xpath("./div/div[7]/span/a")).getAttribute("href");//店铺地址
        }
        ++this.goods_num;
        item.setId(this.goods_num);
        item.setTitle(title);
        item.setPrince(prince);//价格
        if(prince>20000){
            return;
        }
        item.setShop_name(shop_name);//店铺名
        item.setShop_src(shop_src);//店铺地址
        item.setSales(sales);//销量
        item.setGoods_img(goods_img);//商品图片
        item.setGoods_src(goods_src);//详情地址
        item.setTag_name(tagName);
        goodsRepository.save(item);
        tagName = "";
    }

    /**
     * 字符串获取数字
     * TODO 使用正则表达式，将数据进行提取
     *
     * @param str
     * @return
     */
    private Double getNumber(String str) {
        String s = Pattern.compile("[^0-9.]+").matcher(str).replaceAll("");
        if(s.equals("")){
            s = "0";
        }
        Double num = Double.valueOf(s);
        return num;
    }

    /**
     * 转化评论数
     * TODO 提取字符串内容将数据进行判断拼接。转化万为10000
     *
     * @param commit_num
     * @return
     */
    public Integer getCommitNum(String commit_num) {
        String commit = "";
        List<String> commit_temp = Arrays.asList(commit_num.split(""));
        for (String text : commit_temp) {
            if (text.equals("万")) {
                text = "0000";
            } else if (text.equals("+")) {
                break;
            } else if (text.equals("(") || text.equals(")")) {
                continue;
            }
            commit += text;
        }
        if(commit.equals("")){
            commit = "0";
        }
        return Integer.valueOf(commit);
    }

    /**
     * 访问地址
     *
     * @param edge
     * @param url
     * @throws InterruptedException
     */
    private void openUrl(EdgeDriver edge, String url) throws InterruptedException {
        edge.get(url);
        edge.executeScript(this.js_bottom);//向下滚动
        Thread.sleep(this.sleep);
    }

    /**
     * // TODO: 2021/3/6 输入code状态码发送信息，使用code。XXX获取
     * @param code_info
     */
    private void sendText(Integer code_info){
        HashMap<String,Object> meta = new HashMap<>();
        meta.put("code",code_info);
        meta.put("msg",code.getMsg(code_info));
        HashMap<String,Object> result = new HashMap<>();
        result.put("meta",meta);
        try {
            MetaWebSocket.sendMessage(encodeJson.encode(result));
        } catch (EncodeException e) {
            e.printStackTrace();
        }
        meta.clear();
        result.clear();
    }
}
